package com.allenkerr.other;

import org.junit.Test;

import java.io.UnsupportedEncodingException;
import java.util.Arrays;
import java.util.Random;

/**
 * Created by 小柯 on 17/7/6.
 */
public class OtherTest01 {

    /**
     * https://my.oschina.net/u/347386/blog/182717
     */
    @Test
    public void test1() {
        for (int i = 0; i < 16; i++) {
            String hexString = Integer.toHexString(i);
            System.out.println(i + " --> " + hexString);
        }
    }

    @Test
    public void test2() {
        int i = 1 ^ 2;
        int j = 2 ^ 2;
        System.out.println("i = " + i);
        System.out.println("j = " + j);
    }

    @Test
    public void test3() throws UnsupportedEncodingException {
//        byte[] bytes = {1, 1, 1, 1};
        byte[] bytes = {1, 1, 1, 1, 1, 1, 1, 1};
//        String binaryString = bytes2binaryString(bytes);
//        String hexString = bytes2hexString(bytes);
//        System.out.println("binaryString = " + binaryString);
//        System.out.println("hexString = " + hexString);

//        String hexString = bytesToHexString(bytes);
//        System.out.println("hexString = " + hexString);

        int number = 0;
        for (int i = bytes.length - 1; i >= 0; i--) {
            number = number * 2 + bytes[i];
        }
        String hexString = Integer.toHexString(number);
        System.out.println("number = " + number);
        System.out.println("hexString = " + hexString);

//        String hexString2 = new String(bytes, "UTF-8");
//        System.out.println("hexString2 = " + hexString2);
    }

    @Test
    public void test3_1() {
        Random random = new Random();
        for (int i = 0; i < 20; i++) {
            int length = 8;
            byte[] bytes = new byte[length];
            //随机创建 bytes
            for (int j = 0; j < length; j++) {
                boolean b = random.nextBoolean();
                bytes[j] = (byte) (b ? 1 : 0);
            }
            System.out.println(Arrays.toString(bytes));

//            String hex = this.byte2hex(bytes);
//            String hex = this.bytes2hex03(bytes);
//            String hex = this.toHexString1(bytes);
//            String hex = this.toHexString2(bytes);
//            int intNumber = this.byteArrayToInt(bytes);
//            String hex = Integer.toHexString(intNumber);

            //by 小柯
            int number = this.bytesToInt(bytes);
            String hex = Integer.toHexString(number);

            System.out.println("number = " + number);
            System.out.println(hex + "\n");

        }
    }

    /**
     * http://www.voidcn.com/blog/hll174/article/p-5760755.html
     * 十进制转成十六进制    String Integer.toHexString(int i)
     * 十进制转成八进制      String Integer.toOctalString(int i)
     * 十进制转成二进制      String Integer.toBinaryString(int i)
     * 十六进制转成十进制    Integer.valueOf("FFFF",16).toString()   //不能处理带前缀的情况 0x
     * 八进制转成十进制      Integer.valueOf("76",8).toString()  //前缀0可以被处理
     * 二进制转十进制       Integer.valueOf("0101",2).toString()
     */
    @Test
    public void test3_2() {
        int length = 16;
        Random random = new Random();
        for (int i = 0; i < 20; i++) {

            StringBuilder binary = new StringBuilder();
            //随机创建 binary String
            for (int j = 0; j < length; j++) {
                boolean b = random.nextBoolean();
                binary.append(b ? 1 : 0);
            }

            //二进制字符串 转 十六进制字符串
            String hex = this.binaryStringToHexString(binary.toString());

            System.out.println("binary = " + binary);
            System.out.println("hex = " + hex + "\n");
        }
    }

    @Test
    public void test3_2_1() throws UnsupportedEncodingException {
        int length = 16;
        Random random = new Random();
        for (int i = 0; i < 20; i++) {
            byte[] bytes = new byte[length];
            //随机创建 bytes
            for (int j = 0; j < length; j++) {
                boolean b = random.nextBoolean();
                bytes[j] = (byte) (b ? 1 : 0);
            }
            String binary = new String(bytes, "UTF-8");
            System.out.println(Arrays.toString(bytes));
            System.out.println("binary = " + binary);
        }
    }

    @Test
    public void test3_4() {

        String binary = "00000011";

        //二进制 转 十进制
        Integer integer = Integer.valueOf(binary, 2);
        //十进制 转 十六进制
        String hex = Integer.toHexString(integer);

        //长度处理
        int capacity = binary.length() >> 2;
        if (hex.length() < capacity) {
            StringBuilder builder = new StringBuilder(capacity);
            for (int i = 0; i < capacity - hex.length(); i++) {
                builder.append("0");
            }
            hex = builder.append(hex).toString();
        }

        System.out.println("binary = " + binary);
        System.out.println("integer = " + integer);
        System.out.println("hex = " + hex);
    }

    /**
     * 二进制字符串 转 十六进制字符串
     *
     * @param binary
     * @return
     * @author 小柯
     */
    public static String binaryStringToHexString(String binary) {
        //二进制 转 十进制
        Integer integer = Integer.valueOf(binary, 2);
        //十进制 转 十六进制
        String hex = Integer.toHexString(integer);
        //十六进制字符串长度处理
        int capacity = binary.length() >> 2;
        if (hex.length() < capacity) {
            StringBuilder builder = new StringBuilder(capacity);
            for (int i = 0; i < capacity - hex.length(); i++) {
                builder.append("0");
            }
            hex = builder.append(hex).toString();
        }
        return hex;
    }

    @Test
    public void test3_3() {
        int number = 16;
        System.out.println(">> 1  " + (number >> 1));//除以2，8
        System.out.println("<< 1  " + (number << 1));//乘以2，32
        System.out.println("<< 2  " + (number << 2));//乘以4，64

        number = 27 << 2;//108
        System.out.println("number = " + number);
        System.out.println(">> 1  " + (number >> 1));//除以2，54
        System.out.println(">> 2  " + (number >> 2));//除以4，27

        number = 9;
        System.out.println(">> 3  " + (number >> 3));//除以9，1
    }

    /**
     * bytes --> int
     *
     * @param bytes
     * @return
     * @author 小柯
     */
    public static int bytesToInt(byte[] bytes) {
        int value = 0;
        for (int i = bytes.length - 1; i >= 0; i--) {
            value = value * 2 + bytes[i];
        }
        return value;
    }

    /**
     * int到byte[]
     *
     * @param i
     * @return
     */
    public static byte[] intToByteArray(int i) {
        byte[] result = new byte[4];
        //由高位到低位
        result[0] = (byte) ((i >> 24) & 0xFF);
        result[1] = (byte) ((i >> 16) & 0xFF);
        result[2] = (byte) ((i >> 8) & 0xFF);
        result[3] = (byte) (i & 0xFF);
        return result;
    }

    /**
     * byte[]转int
     *
     * @param bytes
     * @return
     */
    public static int byteArrayToInt(byte[] bytes) {
        int value = 0;
        //由高位到低位
        for (int i = 0; i < 4; i++) {
            int shift = (4 - 1 - i) * 2;
            value += (bytes[i] & 0x000000FF) << shift;//往高位游
        }
        return value;
    }

    public static String toHexString2(byte[] bytes) {
        char[] hexArray = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
        char[] hexChars = new char[bytes.length * 2];
        int v;
        for (int j = 0; j < bytes.length; j++) {
            v = bytes[j] & 0xFF;
            hexChars[j * 2] = hexArray[v / 16];
            hexChars[j * 2 + 1] = hexArray[v % 16];
        }
        return new String(hexChars);
    }

    public static String toHexString1(byte[] bytes) {
        StringBuilder hexString = new StringBuilder();

        for (int i = 0; i < bytes.length; i++) {
            String hex = Integer.toHexString(0xFF & bytes[i]);
            if (hex.length() == 1) {
                hexString.append('0');
            }
            hexString.append(hex);
        }

        return hexString.toString();
    }

    /**
     * 方式三
     *
     * @param bytes
     * @return
     */
    public static String bytes2hex03(byte[] bytes) {
        final String HEX = "0123456789abcdef";
        StringBuilder sb = new StringBuilder(bytes.length * 2);
        for (byte b : bytes) {
            // 取出这个字节的高4位，然后与0x0f与运算，得到一个0-15之间的数据，通过HEX.charAt(0-15)即为16进制数
            sb.append(HEX.charAt((b >> 4) & 0x0f));
            // 取出这个字节的低位，与0x0f与运算，得到一个0-15之间的数据，通过HEX.charAt(0-15)即为16进制数
            sb.append(HEX.charAt(b & 0x0f));
        }
        return sb.toString();
    }

    /**
     * 字节数组转换为十六进制字符串
     *
     * @param b byte[] 需要转换的字节数组
     * @return String 十六进制字符串
     */
    public static final String byte2hex(byte b[]) {
        if (b == null) {
            throw new IllegalArgumentException(
                    "Argument b ( byte array ) is null! ");
        }
        String hs = "";
        String stmp = "";
        for (int n = 0; n < b.length; n++) {
            stmp = Integer.toHexString(b[n] & 0xff);
            if (stmp.length() == 1) {
                hs = hs + "0" + stmp;
            } else {
                hs = hs + stmp;
            }
        }
        return hs.toUpperCase();
    }

    @Test
    public void test4() {
        String str = null;
        str = String.format("Hi,%s", "王力");
        System.out.println(str);

        str = String.format("Hi,%s:%s.%s", "王南", "王力", "王张");
        System.out.println(str);

        System.out.printf("字母a的大写是：%c %n", 'A');
        System.out.printf("3>7的结果是：%b %n", 3 > 7);
        System.out.printf("100的一半是：%d %n", 100 / 2);
        System.out.printf("100的16进制数是：%x %n", 100);
        System.out.printf("100的8进制数是：%o %n", 100);
        System.out.printf("50元的书打8.5折扣是：%f 元%n", 50 * 0.85);
        System.out.printf("上面价格的16进制数是：%a %n", 50 * 0.85);
        System.out.printf("上面价格的指数表示：%e %n", 50 * 0.85);
        System.out.printf("上面价格的指数和浮点数结果的长度较短的是：%g %n", 50 * 0.85);
        System.out.printf("上面的折扣是%d%% %n", 85);
        System.out.printf("字母A的散列码是：%h %n", 'A');
    }

    @Test
    public void test5() {
        System.out.printf("100的16进制数是：%x %n", 100); // %x 整数类型（十六进制），%n 换行符

        int[] array = {255, 100, 64, 16, 5};
        for (int i : array) {
            String hex = String.format("%x", i);
            System.out.println(i + " ---> " + hex);
        }
        /**
         * 255 ---> ff
         * 100 ---> 64
         * 64 ---> 40
         * 16 ---> 10
         * 5 ---> 5
         */
    }

    /**
     * byte数组转换为二进制字符串,每个字节以","隔开
     **/
    public static String bytes2binaryString(byte[] b) {
        StringBuffer result = new StringBuffer();
        for (int i = 0; i < b.length; i++) {
            result.append(Long.toString(b[i] & 0xff, 2) + ",");
        }
        return result.toString().substring(0, result.length() - 1);
    }

    /**
     * 二进制字符串转换为byte数组,每个字节以","隔开
     **/
    public static byte[] binaryString2bytes(String hex2Str) {
        String[] temp = hex2Str.split(",");
        byte[] b = new byte[temp.length];
        for (int i = 0; i < b.length; i++) {
            b[i] = Long.valueOf(temp[i], 2).byteValue();
        }
        return b;
    }

    /**
     * byte数组转换为十六进制的字符串
     **/
    public static String bytes2hexString(byte[] b) {
        StringBuffer result = new StringBuffer();
        for (int i = 0; i < b.length; i++) {
            if ((b[i] & 0xff) < 0x10)
                result.append("0");
            result.append(Long.toString(b[i] & 0xff, 16));
        }
        return result.toString().toUpperCase();
    }

    /**
     * 十六进制的字符串转换为byte数组
     **/
    public static byte[] hexString2bytes(String hex16Str) {
        char[] c = hex16Str.toCharArray();
        byte[] b = new byte[c.length / 2];
        for (int i = 0; i < b.length; i++) {
            int pos = i * 2;
            b[i] = (byte) ("0123456789ABCDEF".indexOf(c[pos]) << 4 | "0123456789ABCDEF".indexOf(c[pos + 1]));
        }
        return b;
    }

    /**
     * byte数组转换成16进制字符串
     *
     * @param src
     * @return
     */
    public static String bytesToHexString(byte[] src) {
        StringBuilder stringBuilder = new StringBuilder();
        if (src == null || src.length <= 0) {
            return null;
        }
        for (int i = 0; i < src.length; i++) {
            int v = src[i] & 0xFF;
            String hv = Integer.toHexString(v);
            if (hv.length() < 2) {
                stringBuilder.append(0);
            }
            stringBuilder.append(hv);
        }
        return stringBuilder.toString();
    }
}
